package com.ice.delay.task.core.helper;

import cn.hutool.core.util.ObjectUtil;
import com.ice.delay.task.core.config.DelayTaskConfig;
import com.ice.delay.task.core.enums.ExecuteStatusEnum;
import com.ice.delay.task.core.model.DelayTaskDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.TransactionStatus;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author wangwei
 * @Date 2022/5/30 12:40
 */
@Slf4j
public class TaskScheduleHelper {

    private static TaskScheduleHelper instance = new TaskScheduleHelper();

    public static TaskScheduleHelper getInstance() {
        return instance;
    }


    public static final long PRE_READ_MS = 60 * 1000;    // pre read

    private Thread scheduleThread;

    private volatile boolean scheduleThreadToStop = false;

    public void start() {
        scheduleThread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 随机沉睡
                try {
                    TimeUnit.MILLISECONDS.sleep(60 * 1000 - System.currentTimeMillis() % 1000);
                } catch (InterruptedException e) {
                    if (!scheduleThreadToStop) {
                        logger.error(e.getMessage(), e);
                    }
                }
                logger.info("init task schedule success");
                while (!scheduleThreadToStop) {
                    //
                    // 1、pre read
                    long nowTime = System.currentTimeMillis();
                    DelayTaskConfig.getDelayTaskConfig().executeTransaction(()->{
                        // 获取锁
                        DelayTaskConfig.getDelayTaskConfig().getDelayTaskLockService().selectLock();
                        List<DelayTaskDetail> delayTaskDetails = DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().scheduleTaskQuery(nowTime + PRE_READ_MS);
                        if (ObjectUtil.isNotEmpty(delayTaskDetails)) {
                            // 添加到时间轮中
                            List<String> codes = new ArrayList<>();
                            for (DelayTaskDetail taskDetail : delayTaskDetails) {
                                int time = (int) ((taskDetail.getNotifyNextTime().getTime() - nowTime) / 1000);
                                DelayTaskConfig.getDelayTaskConfig().getTimerWheel().addTimerOneTime(time, aVoid -> {
                                    // 执行任务
                                    DelayTaskDetailRunnableHelper.execute(taskDetail);
                                });
                                codes.add(taskDetail.getCode());
                            }
                            // 更新任务执行状态
                            DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().batchUpdateExecuteStatus(codes, ExecuteStatusEnum.RUNNING.getCode());
                        }
                    });

                    // 沉睡时间
                    try {
                        Thread.sleep(60 * 1000);
                    } catch (InterruptedException e) {
                        if (!scheduleThreadToStop) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                }
            }
        });
        scheduleThread.setName("Task schedule scan");
        scheduleThread.start();
    }

    public void stop() {
        scheduleThreadToStop = true;

    }
}
